﻿using System;
using System.Collections.Generic;
using System.Threading;
using WsProtocol.PublicClass;
using Comm.PublicClass;
using System.Threading.Tasks;

namespace Wasion.HHU.Services
{
    //[Serializable]  
    public class CommAndAnaBase  
    {
        //解析内存表结构     

        private class TAnaType 
        {  
            public string CommName;  //串口号             
              
            public CommConst.TOrdertype recOrder; //待解析的指令类                                                                     

            public bool AnaDone;  //解析结束标志         
            public Int64 recTime;  //接收帧时间                                                 
                  
         
        }

        public int MsgHandle;

        private List<TAnaType> RecInfo = null;
        //private Thread AnalysisThread = null;    //解析线程
        private bool analysis = false;
        private bool frunning = true;  //是否处于运行状态 

        //shaunwang 2014-11-27  
        private static Object objlock = new object();    
         
        public bool Running 
        {
            get { return frunning;} 
            set { frunning = value; }
        }

        public CommAndAnaBase()
        {
            string errinfo = string.Empty; 
            //CommManager.InitCommInfo(ref errinfo);  //初始化通信模块   
            PtlBaseUIProConsts.doAnalysis = AnalysisOrder; //AddReceive;  //绑定解析事件     
            

            if (RecInfo == null)
                RecInfo = new List<TAnaType>(); 


            //if (AnalysisThread == null) //为空则创建解析线程 
            //{
            //    analysis = true;
            //    AnalysisThread = new Thread(new ThreadStart(DoAnalysis));
            //    AnalysisThread.IsBackground = true;
            //    AnalysisThread.Name = "串口解析线程";
            //}
            //AnalysisThread.Start();
        }

        //释放串口 
        //public void CloseComm(string commname)
        //{
        //    try
        //    {
        //        string errinfo = string.Empty;
        //        CommManager.ClearOrder(CommProperty.CommMode.RS232, commname, ref errinfo);  
        //        Thread.Sleep(200);
        //        CommManager.CloseComm(CommProperty.CommMode.RS232, commname, ref errinfo);
        //        //GC.Collect();
        //    }
        //    catch
        //    {
        //    }
        //}

        //停止解析
        //public void StopAnalysis()
        //{
        //    analysis = false;
        //    try
        //    {
        //        if (AnalysisThread != null && AnalysisThread.IsAlive)
        //        {
        //            AnalysisThread.Abort();
        //            //Thread.Sleep(200);
        //            Task.Delay(200).Wait();
        //        }
        //        GC.Collect();
        //    }
        //    catch
        //    {
        //    }
        //}

        //停止所有操作

        //public void StopAll()
        //{
        //    //commRec.Close();
        //    //Thread.Sleep(200);
        //    Task.Delay(200).Wait();
        //    string errinfo = string.Empty;
        //    //CommManager.StopOrder(CommMode.RS232, "", ref errinfo);
        //    //Thread.Sleep(200);
        //    Task.Delay(200).Wait();
        //    StopAnalysis();
        //    //Thread.Sleep(200);
        //    Task.Delay(200).Wait();
        //    //CommManager.ClearOrder(CommMode.RS232, "", ref errinfo);
        //    //Thread.Sleep(200);
        //    Task.Delay(200).Wait();
        //    //CommManager.CloseComm(CommMode.RS232, "", ref errinfo);
        //    GC.Collect();

        //}

        //清除指令
        public void ClearOrder(string commname)
        {
            string errinfo = string.Empty;
            //CommManager.ClearOrder(CommMode.RS232, commname, ref errinfo);
            //Thread.Sleep(200);
            Task.Delay(200).Wait();
        }

        
        /// <summary>
        /// 在解析缓冲区中找一个空的位置

        /// </summary>
        /// <returns></returns>
        private int FindPlace()
        { 
            int newplace = -1;
            for (int i = 0; i < RecInfo.Count; i++)
            {
                //Application.DoEvents();
                if (RecInfo[i].AnaDone)
                {
                    newplace = i;
                    break;
                }
            }
            return newplace;
        }
        
        
        /// <summary>
        /// 将收到的返回帧放入解析缓冲区
        /// </summary>
        /// <param name="newrec"></param>
        private void AddReceive(CommConst.TOrdertype newrec) 
        { 
            TAnaType newAna = new TAnaType();
            newAna.CommName = newrec.commname;  
            newAna.recOrder = newrec;
            newAna.recTime = PubFunction.DateTimeToInt(); //DateTime.Now;   
            newAna.AnaDone = false;
            int newplace = FindPlace();
            if (newplace >= 0)  //找到空位置
            {
                RecInfo[newplace] = newAna;
            } 
            else               //新增一个位置

            {
                RecInfo.Add(newAna);
            }
        }

        /// <summary>
        /// 获取下一个要解析的类
        /// </summary>
        /// <returns></returns>
        private TAnaType getNextAna()
        {
            //DateTime comparetime = DateTime.Now;
            TAnaType nextAna = null;
            if (RecInfo == null)
                return nextAna;

            try
            {
                Int64 comparetime = PubFunction.DateTimeToInt();
                for (int i = 0; i < RecInfo.Count; i++)
                {
                    if (!RecInfo[i].AnaDone && comparetime >= RecInfo[i].recTime)
                    {
                        comparetime = RecInfo[i].recTime;
                        nextAna = RecInfo[i];
                    }
                }
            }
            catch
            { }
            if (nextAna != null)
                nextAna.AnaDone = true;
            return nextAna;
        }


        
        
        /// <summary>
        /// 解析过程
        /// </summary>
        protected virtual void DoAnalysis()
        {
            TAnaType currentRec = null;
            while (analysis)
            {
                //Application.DoEvents();
                //Thread.Sleep(1); //shaunwang mark
                Task.Delay(1).Wait();
                currentRec = getNextAna(); 
                if (currentRec != null)
                {                    
                    try
                    {
                        string anaCommName = currentRec.CommName;
                        CommConst.TOrdertype nowOrder = currentRec.recOrder;
                        AnalysisOrder(nowOrder);
                    }
                    finally
                    {
                        currentRec.AnaDone = true;
                        GC.Collect();
                    }               
                
                }
            
            }
        
        }


        protected virtual void AnalysisOrder(CommConst.TOrdertype nowOrder)
        {
            try
            {
                //Log.WriteMeterLog(nowOrder.order, nowOrder.recstr, "开始解析");

                //在这里记录所有收发帧
                if (nowOrder.sendFrame == string.Empty)
                    nowOrder.sendFrame += nowOrder.realorder;
                else
                {
                    if (nowOrder.sendFrame.IndexOf(nowOrder.realorder) < 0)
                        nowOrder.sendFrame += ";" + nowOrder.realorder;
                }


                if (nowOrder.recFrame == string.Empty)
                    nowOrder.recFrame += nowOrder.recstr;
                else
                {
                    if (nowOrder.recFrame.IndexOf(nowOrder.recstr) < 0)
                        nowOrder.recFrame += ";" + nowOrder.recstr;
                }


                if (nowOrder.AnaPtl == null)  //不用解析
                {
                    nowOrder.Success();
                    return;
                }
                if (nowOrder.SendFlag != CommConst.CommFlag.CommReceived || nowOrder.errorinfo != string.Empty) //
                {
                    //Log.WriteMeterLog(nowOrder.order, nowOrder.recstr, "指令状态：" + nowOrder.SendFlag.ToString() + "   错误信息：" + nowOrder.errorinfo);
                    return;
                }


                string errinfo = "";
                PtlBase anaptl = (PtlBase)nowOrder.AnaPtl;

                int rs = anaptl.ResolveFrame(nowOrder.recstr, ref errinfo);  //分解
                if (rs <= 0)
                {
                    //解析失败
                    nowOrder.Fail(true, "分解返回帧异常:" + errinfo);
                    return;
                }
                else
                    if (rs == 2)  //要重发
                    {
                        if (nowOrder.dotimes < nowOrder.maxdotimes)
                            nowOrder.Reset(false);
                        else
                            nowOrder.Fail(false, errinfo);
                        return;
                    }

                //匹配收发帧
                errinfo = anaptl.CompareFrame(nowOrder.realorder, nowOrder.recstr, nowOrder.RWFlag, -1);
                if (!string.IsNullOrEmpty(errinfo))
                {
                    //解析失败
                    nowOrder.Fail(true, errinfo);
                    return;
                }


                if (!nowOrder.NeedAna)  //不用解析
                {
                    nowOrder.Success();
                    return;
                }

                //nowOrder.tmpdata.Add(anaptl.GetData());  //数据域加入缓冲区

                //链路层分帧处理
                if (!string.IsNullOrEmpty(anaptl.ptlinfo.ContinueOrder)) 
                {
                    if (!string.IsNullOrEmpty(nowOrder.order))
                    {
                        nowOrder.ResetComm = false;  //分帧不需要重新检查连接或握手
                        nowOrder.Refresh(anaptl.ptlinfo.DataName, anaptl.ptlinfo.ContinueOrder, false, anaptl.NeedReturn());//
                    }
                    return;
                }

                ////将缓冲区中保存的临时数据域拼凑起来
                //string alldata = "";
                //for (int i = 0; i < nowOrder.tmpdata.Count; i++)
                //    alldata += nowOrder.tmpdata[i];
                //anaptl.SetData(alldata);

                //开始解析
                rs = anaptl.AnalizeFrame(ref errinfo);

                if (rs >= 0)  //解析成功
                {
                    nowOrder.ResetComm = false; //分帧不需要重新检查连接或握手
                    if (anaptl.ptlinfo.AnaDone)  //本次通信已解析
                    {
                        anaptl.ptlinfo.AnaDone = false;
                        if (nowOrder.DoAfterAnalysis != null)
                            nowOrder.DoAfterAnalysis(nowOrder);                        
                        
                        //增加针对下发指令分帧的情况做处理
                        if (nowOrder.SendNext() > 0)
                            return;
                        if (errinfo != "")
                            nowOrder.errorinfo = errinfo;
                    }

                    //应用层分帧处理
                    if (!string.IsNullOrEmpty(anaptl.ptlinfo.ContinueOrder))
                    {
                        
                        //nowOrder.Refresh(anaptl.ptlinfo.DataName, anaptl.ptlinfo.ContinueOrder);
                        nowOrder.Refresh(anaptl.ptlinfo.DataName, anaptl.ptlinfo.ContinueOrder, false, anaptl.NeedReturn());//
                        return;
                    }

                    nowOrder.Success();
                }
                else
                {
                    //解析失败
                    nowOrder.Fail(false, "解析异常:" + errinfo);
                }
            }
            catch (Exception ex)
            {
                nowOrder.Fail(false, "解析异常:" + ex.Message);
            }
            
        }
    
    }

}


